<template>
  	<div class="editor">
		<div class="toolbar" height="50px">
			<select v-model="activePageIndex"  v-if="activePageIndex>=0 && pages.length>0">
				<option :key="`sp_${i}`" :value="i" v-for="(page,i) in pages">{{page.title}}</option>
			</select>
			<button @click="()=>{addPage()}">添加页面</button>
			<button @click="deletePage">删除当前页面</button>
			<button @click="cmdo('undo')">撤销</button>
			<button @click="cmdo('redo')">重做</button>
			<button @click="save">保存</button>
			<button @click="view">预览</button>
		</div>
		<div class="mainpanel">
			<div class="itempanel">
				<ul v-if="pages.length>0">
					<li  v-for="item in items" :key="item.type" v-on:click="itemClick(item.type)" :class="checkedItemType === item.type?'checked':''">
						<span>
							<i :class="`item-icon ${item.icon}`"></i>
							{{item.txt}}
						</span>
					</li>
				</ul>
			</div>
			<div class="page" @contextmenu.prevent>				
				<div class="svgs" v-if="activePageIndex>=0" :style="`width:${pages[activePageIndex].size.width}px`">								
					<svg ref="pageSvg" v-if="pages.length>0"
						:id="`page_${activePageIndex}`" 						
						:width="pages[activePageIndex].size.width" 
						:height="pages[activePageIndex].size.height" 
						:class="`pagesvg ${pages[activePageIndex].gridVisible?'pagegrid':''}`" 
						@click="(v)=>{ pageClick('page',v);}"
						@mousemove="mouseMove" 
						@mouseup.left="mouseUp"
						@mousedown.left="mouseDown"
						@mouseup.right="mouseUpRight" 
						@contextmenu.prevent
						:style="`background-color:${pages[activePageIndex].backgroundColor}`">	
						<svgPicker :visible="pages[activePageIndex].svgPickerVisible" :startXY="pages[activePageIndex].mouseDownXY" :startEvent="pages[activePageIndex].mouseDownEvent" :moveEvent="mouseMoveEvent" :items="pages[activePageIndex].items" @select="(items)=>{this.itemsInstanceSelected(items)}"/>										
					</svg>
				</div>		
			</div>
			<div class="detailpanel">
				<input class="page-title" v-model="pages[activePageIndex].title" v-if="activePageIndex>=0 && pages.length>0" maxlength="40"/>
				<div ref="detailpanel" v-if="activePageIndex>=0 && pages.length>0">
					<pageAttr :attr="pages[activePageIndex]" v-if="checkedType === 'page'" @sizeChange="(size)=>{this.pages[this.activePageIndex].size = size;}" @change="(v)=>{this.pages[this.activePageIndex] = v;}" />
				</div>				
			</div>
		</div>
		<contextMenu ref="cxtMenu" :cmdActive="cmdActive" @command="(cmd,args)=>{this.cmdo(cmd,args)}" :page="pages[activePageIndex]" v-if="activePageIndex>=0 && pages.length>0" />
		<div class="view" :style="`display:${viewVisible?'flex':'none'};`">
			<div class="view-close" @click="viewVisible=false">✖</div>
			<viewer ref="viewer"/>
		</div>
	</div>
</template>
<script>
import commands from './commands'
import {items} from './items'
import pageAttr from "./pageAttr"
import svgPicker from "./tools/svgPicker"
import contextMenu from "./tools/contextMenu"
import viewer from "./viewer"
import helper from './helper'

export default {
	name: "editor",
	mixins:commands,
	components: { pageAttr,svgPicker,contextMenu,viewer },
	props:{
		items:{type:Array,default:items},
		undoRecordsNum:{type:Number,default:100},//记录历史操作记录条数
		data:{type:Array,default:()=>{return []}}
	},
	data(){
		return{
			checkedType:'page',
			checkedItemType:'',
			activePageIndex:0,
			mouseMoveEvent:null,
			dragOffset:null,
			currentClientXY:{x:0,y:0},
			activePageId:null,
			viewVisible:false,
			pages:[{
				title:'页面名称',
				size:{ width:1024,height:768},//页面尺寸
				gridVisible:true,//是否显示网格
				isMain:true,
				backgroundColor:'#FFFFFF',
				items:[],
				resizeIdx:-1,
				resizeType:'',
				dragIdx:-1,
				svgPickerVisible:false,
				mouseDownEvent:null,
				mouseDownXY:{x:0,y:0},
				mouseUpRightEvent:null,
				cxtMenuVisible:false,
				id:new Date().getTime()
			}]
		}
	},
	watch:{
		activePageIndex(n,o){
			console.log(`watch pidx n:${n},o:${o}`);
			this.switchPageIdx(n,o);
		}
	},
	computed: {		
		getCheckedItem:function(){
			if(this.activePageIndex >= 0){				
				var arr = this.pages[this.activePageIndex].items.filter(item=>{return item.checked});
				if(arr.length>0){
					return arr[0];
				}
			}
			return null;
		},
		slectedCount:function(){
			if(this.activePageIndex >=0 && this.pages[this.activePageIndex].items){
				console.log('slectedCount',typeof(this.pages[this.activePageIndex].items),this.pages[this.activePageIndex]);
				return this.pages[this.activePageIndex].items.filter(item=>{return item.selected}).length;
			}
			return 0;
		}
	},
	mounted(){
        var that=this;
        window.addEventListener("keydown", (event)=>{            
            that.commandKey(event);
		});
	},
	methods:{
		setData:function(pages){	
			this.switchPageIdx(-1);			
			this.pages.splice(0,this.pages.length);
			pages.forEach(page=>{
				this.pages.push(Object.assign(page,{
					resizeIdx:-1,
					resizeType:'',
					dragIdx:-1,
					svgPickerVisible:false,
					mouseDownEvent:null,
					mouseDownXY:{x:0,y:0},
					mouseUpRightEvent:null,
					cxtMenuVisible:false,
					gridVisible:true
				}));
			});
			this.switchPageIdx(0);
		},
		save:function(pages){			
			var data = JSON.parse(JSON.stringify(this.pages));
			console.log('save',data);
			this.$emit("onSave",data);
		},
		addPage:function(page){
			if(!page){
				page={
					title:`新建页面${this.pages.length}`,
					size:{ width:1024,height:768},//页面尺寸
					gridVisible:true,//是否显示网格
					isMain:false,
					backgroundColor:'#FFFFFF',
					items:[],
					resizeIdx:-1,
					resizeType:'',
					dragIdx:-1,
					svgPickerVisible:false,
					mouseDownEvent:null,
					mouseDownXY:{x:0,y:0},
					mouseUpRightEvent:null,
					cxtMenuVisible:false
				};
			}else{
				page=Object.assign(page,{
					resizeIdx:-1,
					resizeType:'',
					dragIdx:-1,
					svgPickerVisible:false,
					mouseDownEvent:null,
					mouseDownXY:{x:0,y:0},
					mouseUpRightEvent:null,
					cxtMenuVisible:false,
					gridVisible:true
				});
			}
			
			//console.log('addpage',page);
			this.pages.push(page);
			this.switchPageIdx(this.pages.length-1);
		},
		deletePage:function(){			
			this.itemsInstanceUnChkSel(this.activePageIndex);
			//console.log('deletePage',this.pages.length,helper.clone(this.pages));
			var pageIdx=this.activePageIndex;
			if(this.pages.length === 1){
				this.pages.splice(this.activePageIndex,1);
				this.addPage();				
			}else{							
				//this.activePageIndex=0;
				this.switchPageIdx(0);
				this.pages.splice(pageIdx,1);				
			}
			if(pageIdx === 0){
				this.clearSVG();
				var items=JSON.parse(JSON.stringify(this.pages[this.activePageIndex].items));
				this.pages[this.activePageIndex].items=[];
				items.forEach(element=>{
					this.renderItem(this.pages[this.activePageIndex],element);
				});
			}
		},
		switchPageIdx:function(index,o){
			// console.log(`switchPageIdx:index-${index}=>o-${o} || activePageIndex-${this.activePageIndex}=>index-${index}`);			
			if(isNaN(o) && index === this.activePageIndex) return;			
			if(!isNaN(o) && o>=0){
				this.itemsInstanceUnChkSel(o);	
			}else{
				this.itemsInstanceUnChkSel(this.activePageIndex);	
			}
			// console.log(`switchPageIdx:${index}=>${o} || ${this.activePageIndex}=>${index}`);
			this.activePageIndex=index;
			this.clearSVG();
			if(index>=0 && index < this.pages.length){				
				var items=JSON.parse(JSON.stringify(this.pages[index].items));				
				this.pages[index].items=[];
				items.forEach(element=>{
					this.renderItem(this.pages[index],element);
				});	
			}			
		},
		clearSVG:function(){
			//console.log('clearSVG in');
			if(this.$refs.pageSvg && this.$refs.pageSvg.querySelectorAll){
				//console.log('clearSVG');
				this.$refs.pageSvg.querySelectorAll(".editor-element").forEach(element=>{
					this.$refs.pageSvg.removeChild(element);
				});
			}
		},
		view:function(){
			this.$refs.viewer.showPage(helper.clone(this.pages[this.activePageIndex]));
			this.viewVisible=true;
		},
		pageClick:function(page,event){//点击页面事件
			//console.log('pageClick:page-',page,'-',this.checkedType,event);
			if(this.checkedItemType !==''){
				//console.log(`pageClick checkedItemType:${this.checkedItemType},checkedType:${this.checkedType}`,event);
				var xy=helper.svgClickXY(this.pages[this.activePageIndex],event);
				var item = this.renderItem(this.pages[this.activePageIndex],
					{
						type:this.checkedItemType,
						x:xy.x,
						y:xy.y,
						lock:false //锁定位置和大小,0-否,1-是
					},event);
				this.checkedItemType='';
				this.itemInstanceChecked(item,event);
				this.cmdo('records');
				return;
			}		
		},
		itemClick:function(itemType){		
			this.checkedItemType=itemType;
			//console.log('itemClick:',itemType,'-checkedType',this.checkedType)
		},				
		itemInstanceChecked:function(item,event){
			this.checkedType=item.type;
			this.checkedItemType='';
			// this.pages[this.activePageIndex].items.forEach((element,i) => {
			// 	console.log(`schk idx:${element.idx},checked:${element.checked},selected:${element.selected},clk:${i === item.idx}`)
			// });
			var itemSelected=item.selected;
			this.pages[this.activePageIndex].items.forEach((element,i) => {
				if(i === item.idx){
					this.$set(this.pages[this.activePageIndex].items[element.idx],"checked",true);
					this.$set(this.pages[this.activePageIndex].items[element.idx],"selected",true);
					//console.log(`itemInstanceChecked,idx:${element.idx},i===item.idx`);
				}else if((event && event.ctrlKey) || itemSelected){
					element.checked=false;
					// console.log(`itemInstanceChecked,ctrlKey,idx:${element.idx},element.checked=false,element.selected = ${element.selected}`);
				}else{
					// console.log(`itemInstanceChecked,idx:${element.idx},element.checked=false,element.selected = false`);					
					this.$set(this.pages[this.activePageIndex].items[element.idx],"checked",false);
					this.$set(this.pages[this.activePageIndex].items[element.idx],"selected",false);
				}
			});

			// this.pages[this.activePageIndex].items.forEach((element,i) => {
			// 	console.log(`echk idx:${element.idx},checked:${element.checked},selected:${element.selected},clk:${i === item.idx}`)
			// });

			if(event) {
				event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
			}		
		},
		itemsInstanceSelected:function(items){		
			items.forEach(element=>{				
				this.$set(this.pages[this.activePageIndex].items[element.idx],"selected",true);
			});
		},
		itemsInstanceUnChkSel:function(pageIdx){
			if(pageIdx < 0) return;
			this.checkedType='page';
			if(pageIdx < this.pages.length && this.pages[pageIdx].items){
				this.pages[pageIdx].items.forEach((element,i) => {
					element.checked=false;
					element.selected=false;
				});
			}
		},
		itemResizeTimer:function(){
			var that=this;
			setTimeout(function(){
				if(that.pages[that.activePageIndex].resizeIdx>=0){
					var item=that.pages[that.activePageIndex].items[that.pages[that.activePageIndex].resizeIdx];
					var resizeType = that.pages[that.activePageIndex].resizeType;
					var moveXY={x:that.mouseMoveEvent.clientX,y:that.mouseMoveEvent.clientY};
					helper.resize(item,resizeType,moveXY,that.currentClientXY);
					that.currentClientXY=moveXY;
					that.itemResizeTimer();
				}
			},50);
		},
		itemResizeDown:function(idx,resizeType){
			//console.log('Editor-itemResizeDown:',idx)
			this.pages[this.activePageIndex].resizeIdx=idx;
			this.pages[this.activePageIndex].resizeType=resizeType;
			this.currentClientXY={x:event.clientX,y:event.clientY};
			this.mouseMoveEvent=event;
			this.itemResizeTimer();
		},
		itemDetailChange:function(item){
			this.pages[this.activePageIndex].items[item.idx].y=item;
		},
		itemDragTimer:function(){
			var that=this;
			setTimeout(()=>{
				if(that.pages[that.activePageIndex].dragIdx<0) return;
				var moveXY={x:that.mouseMoveEvent.clientX-that.currentClientXY.x,y:that.mouseMoveEvent.clientY-that.currentClientXY.y};
				if(moveXY.x != 0 || moveXY.y != 0){
					var dragableX=true;
					var dragableY=true;
					that.pages[that.activePageIndex].items.forEach(item=>{
						if(item.selected){
							var its = this.items.filter(e=>e.type === item.type)[0];
							if(dragableX){
								if(its.methods['dragableX']) {
									dragableX=its.methods['dragableX'](item,moveXY,that.mouseMoveEvent);	
								}else{
									dragableX=this._dragableX(item,moveXY,that.mouseMoveEvent);
								}		
							}
							if(dragableY){
								if(its.methods['dragableY']) {
									dragableY=its.methods['dragableY'](item,moveXY,that.mouseMoveEvent);	
								}else{
									dragableY=this._dragableY(item,moveXY,that.mouseMoveEvent);
								}
							}
						}
					});
					if(dragableX || dragableY){
						that.pages[that.activePageIndex].items.forEach(item=>{
							if(item.selected){	
								var its = this.items.filter(e=>e.type === item.type)[0];
								if(dragableX) {
									if(its.methods['dragX']) {
										its.methods['dragX'](item,moveXY,that.mouseMoveEvent);	
									}else{
										this._dragX(item,moveXY,that.mouseMoveEvent);
									}
								}			
								if(dragableY) {
									if(its.methods['dragY']) {
										its.methods['dragY'](item,moveXY,that.mouseMoveEvent);	
									}else{
										this._dragY(item,moveXY,that.mouseMoveEvent);
									}
								} 
							}
						});
					}					
					that.currentClientXY={x:that.mouseMoveEvent.clientX,y:that.mouseMoveEvent.clientY};
				}
				that.itemDragTimer();
			},50);
		},
		itemDrag:function(idx,event){
			if(idx<0) return;			
			this.pages[this.activePageIndex].dragIdx=idx; 
			this.mouseMoveEvent=event;
			this.currentClientXY={x:event.clientX,y:event.clientY};
			this.itemDragTimer();
		},
		mouseMove:function(event){
			this.mouseMoveEvent=event;
		},
		mouseUp:function(event){
			if(this.pages[this.activePageIndex].resizeIdx>=0){
				this.mouseMove(event);
				this.pages[this.activePageIndex].resizeIdx=-1;
				this.cmdo('records');
			}else if(this.pages[this.activePageIndex].dragIdx>=0){
				var dragIdx=this.pages[this.activePageIndex].dragIdx;
				this.mouseMove(event);
				this.pages[this.activePageIndex].dragIdx=-1;
				this.cmdo('records');
			}			
			if(this.pages[this.activePageIndex].svgPickerVisible){				
				this.pages[this.activePageIndex].svgPickerVisible=false;
			}
		},
		mouseDown:function(event){
			if(this.checkedType == 'page' && this.checkedItemType ==''){
				this.pages[this.activePageIndex].mouseDownEvent=event;
				this.mouseMoveEvent=event;
				this.pages[this.activePageIndex].mouseDownXY=helper.svgClickXY(this.pages[this.activePageIndex],this.pages[this.activePageIndex].mouseDownEvent);				
				this.pages[this.activePageIndex].svgPickerVisible=true;
			}
			this.itemsInstanceUnChkSel(this.activePageIndex);
		},
		mouseUpRight:function(event){
			// console.log('mouseUpRight',event)
			this.pages[this.activePageIndex].mouseUpRightEvent=event;
			//this.pages[this.activePageIndex].cxtMenuVisible=true;
			this.$refs.cxtMenu.show(event);
		},		
		renderItem:function(page,item){//加载item
			var that=this;
			item.idx=page.items.length;
			item.pageSize=page.size;
			item.selected=false;
			item.checked=false;
			item.onChecked=(el,event)=>{//选中控件回调
				//console.log('onChecked',el,event)
				return function(){
					that.itemInstanceChecked(el,event);
				}
			};
			
			item.onUnChecked=(el,event)=>{//选中控件回调
				return function(){
					that.$set(that.pages[that.activePageIndex].items[el.idx],'selected',false);
					that.$set(that.pages[that.activePageIndex].items[el.idx],'checked',false);					
				}
			};

			item.onSelected=(el,event)=>{//选择控件回调
				return function(){
					that.itemsInstanceSelected([el],event);
				}
			};

			item.onUnSelected=(el,event)=>{//取消选择控件回调
				return function(){
					that.itemsInstanceSelected([el],event);
				}
			};

			item.onResizeDown=(idx,resizeType)=>{
				return function(){
					that.itemResizeDown(idx,resizeType);
				}
			};

			item.onDragDown=(idx,resizeType)=>{
				return function(){
					that.currentClientXY={x:event.clientX,y:event.clientY};
					that.itemDrag(idx,event);
				}
			};

			item.onDetailChange=(item)=>{
				return function(){
					that.itemDetailChange(item);
				}
			};

			item.onUpdateAttr=(item,attr,v)=>{
				return function(){
					that.$set(that.pages[that.activePageIndex].items[item.idx],attr,v);
				}
			};
			
			if(item.x<=0){
				item.x=5;
			}else if(item.x > page.size.width){
				item.x=page.size.width-10;
			}

			if(item.y<=0){
				item.y=5;
			}else if(item.y > page.size.height){
				item.y=page.size.height-10;
			}
			
			var its = this.items.filter(e=>e.type === item.type)[0];			
			item=its.methods['install'](item,page,event);
			page.items.push(item);
			its.methods['render'](this.$refs.pageSvg,item);
			its.methods['detailRender'](this.$refs.detailpanel,item);				
			
			//item=this[`${item.type}Install`](page,item,event);
			//page.items.push(item);
			return item;
		},
		itemDetailRender:function(item){
			if(item){
				var its = this.items.filter(e=>e.type === item.type)[0];
				its.methods['detailRender'](this.$refs.detailpanel,item);				
			}
		},
		_dragableX:function(item,moveXY,event){//可被控件自定义方法,在控件index.js中定位方法dragableX
            if(item.lock) return true;
            return moveXY.x+item.x>=0 && moveXY.x+item.x<=item.pageSize.width-item.width;
        },
        _dragableY:function(item,moveXY,event){//可被控件自定义方法,在控件index.js中定位方法dragableY
            if(item.lock) return true;
            return moveXY.y+item.y>=0 && moveXY.y+item.y<=item.pageSize.height-item.height;
        },
        _dragX:function(item,moveXY,event){//可被控件自定义方法,在控件index.js中定位方法dragX
            if(item.lock) return;
            item.x=moveXY.x+item.x;
        },
        _dragY:function(item,moveXY,event){//可被控件自定义方法,在控件index.js中定位方法dragY
            if(item.lock) return;
            item.y=moveXY.y+item.y;
        },
        _pasteXY:function(item){//可被控件自定义方法,在控件index.js中定位方法pasteXY
            item.x=item.x+50;
            item.y=item.y+50;
        }
	}
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.editor{
	position: relative;
	width: 100%;
	height: 100%;
}
.mainpanel{
	position: absolute;
	left:0;
	top:42px;
	height: calc(100% - 42px);
	width:100%;
}

.toolbar {
  padding: 8px 0px;
  width: 100%;
  border-bottom: 1px solid #020202;
  height: 42px;
  z-index: 3;
//   box-shadow: 0px 8px 12px 0px rgba(0, 52, 107, 0.04);
  position: absolute;
  box-sizing: border-box;
  background: #2C2C2C;
}

.page{
	position: absolute;
	height:100%;
	width:calc(100% - 300px);
	margin:0 200px 0 100px;
	box-sizing: border-box;
	overflow: auto;
	background-color:#2c2c2cb5;
}

.svgs{
	display: flex;
	height:100%;
	justify-content: center;
	align-items:center;
	margin:auto;
}
.itempanel{
    height: 100%;
    position: absolute;
    left: 0px;
    z-index: 2;
    background: #2C2C2C;
    width: 100px;
	box-sizing: border-box;
	color:#fff;
}

.itempanel ul{
	display: block;
	padding: 0;
	margin: 0;
}

.itempanel ul li{
	display: inline-block;
	padding: 0;
	margin: 0;
	width:49px;
	height:49px;
	cursor: pointer;
	text-align: center;
	font-size: 12px;
}

.itempanel ul li span i{
	display:block;
	margin-top: 10px;
} 
.itempanel ul li:hover,.itempanel ul li.checked{
	background-color: #E6E9ED;
	color:black;
} 

.detailpanel{
    height:100%;
    position: absolute;
    right: 0px;
    z-index: 2;
    background: #2C2C2C;
    width: 200px;
    padding-top: 8px;
	box-sizing: border-box;
	padding:5px 0;
}

.page-title {
    border: none;
    background: #3f3f3c;
    font: 15px/normal sans-serif;
    text-align: center;
    color: #4F80FF;
    padding: 5px;
    height: 24px;
    margin-left:5px;
}
.page-title input:active {
    cursor: move;
    cursor: -webkit-grab;
    cursor: -moz-grab;
    outline: none;
}
.pagesvg{
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}
.pagegrid{
	background-position: 100% 0;
    background-repeat: repeat;
    background-size: 20px 20px;
    background-image: linear-gradient(transparent 19px, #eee 19px, #eee 20px), linear-gradient(90deg, transparent 19px, #eee 19px, #eee 20px);
}

.view{
	position:absolute;
	height:100%;
	width:100%;
	justify-content: center;
	align-items: center;
	background: #00000099;
	z-index: 5;
}

.view-close{
	position:absolute;
	right:20px;
	top:20px;
	width:25px;
	height:25px;
	font-size: 20px;
	line-height: 25px;
	background: #fff;
	text-align: center;	
	cursor: pointer;
}
</style>
